上一篇我們透過使用者故事、使用案例、驗收標準,把痛點轉化為更嚴謹的規格,了解使用者想做什麼、系統該做什麼反應。但軟體系統不能只有動態行為,還必須有承載這些行為的靜態結構。如果直接開工寫程式,把所有資訊硬塞進單一陣列或物件,資料很快就會因為冗餘與關聯混亂而崩塌。今天要做的是領域概念建模,學習如何從規格中找出實體,並用實體關聯圖(ERD)與基數關係(Cardinality),為代購 App 畫出第一份資料架構藍圖。
定義:一種用於資料庫設計的結構化圖表,透過視覺化方式呈現系統範圍內的核心實體(Entities)以及實體之間的關聯(Relationships)。
定義:實體代表系統中可被獨立定義、儲存資料的物件、概念或事件。在資料庫中,一個實體通常對應成一張資料表(Table);在應用程式邏輯中,則常對應一個資料模型(Model)物件。
實體分類:
基數關係 Cardinality 描述的是兩個實體之間,一筆記錄最多能對應到幾筆記錄:
先列出三個實體:
買家與訂單是一對多:一位買家可以有多筆訂單,每筆訂單只屬於一位買家,訂單表裡的買家 ID 就是外鍵。
但訂單跟商品是多對多:一筆訂單可能包含好幾項商品,同一項商品也會出現在很多筆訂單裡。這種關係沒辦法直接連兩張表,所以要加一個關聯實體「訂單明細 OrderItem」,欄位是訂單 ID(外鍵)、商品 ID(外鍵)、數量,這兩個外鍵合起來就是它的複合主鍵。多對多的關係就這樣被拆成兩個一對多:訂單對訂單明細、商品對訂單明細。
這篇最核心的收穫是想通主鍵和外鍵怎麼搭配著用:外鍵不是憑空出現的欄位,它存在的唯一理由就是指向另一張表的主鍵,把兩個實體之間的關係用資料表達出來。而多對多沒辦法直接建表這件事,也解釋了為什麼幾乎每個訂單系統都會多一張「明細」表——那不是設計者想把系統做複雜,是關聯式資料庫的結構逼出來的必要安排。剛開始讀這些名詞完全沒有概念——強實體、弱實體、關聯實體、複合屬性、衍生屬性,一連串很長的串術語混在一起看,根本分不出誰是誰。我的解決方式是用實例去思考:把買家、商品、訂單這三個實體實際擺出來,一邊對著關係圖一邊問自己「這個屬性是不是可以由別的欄位算出來?」、「這兩個實體算不算獨立存在,還是誰依賴誰?」,名詞之間的關係才慢慢清楚起來,而不是靠死記活背。